﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.IO;
using SevenZip;
using System.Threading;

// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service" in code, svc and config file together.
public class TransferService : ITransferService
{
    public RemoteFileInfo DownloadFile(DownloadRequest request)
    {
        RemoteFileInfo result = new RemoteFileInfo();
        try
        {
            string filePath = System.IO.Path.Combine(@"c:\UploadFiles", request.FileName);
            System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);

            // check if exists
            if (!fileInfo.Exists)
                throw new System.IO.FileNotFoundException("File not found",
                                                          request.FileName);

            // open stream
            System.IO.FileStream stream = new System.IO.FileStream(filePath,
                      System.IO.FileMode.Open, System.IO.FileAccess.Read);

            // return result 
            result.FileName = request.FileName;
            result.Length = fileInfo.Length;
            result.FileByteStream = stream;
        }
        catch (Exception ex)
        {

        }
        return result;
    }
    public void UploadFile(RemoteFileInfo request)
    {
        try
        {
            FileStream targetStream = null;
            Stream sourceStream = request.FileByteStream;

            string uploadFolder = @"C:\upload\temp\";

            string filePath = Path.Combine(uploadFolder, request.FileName);

            using (targetStream = new FileStream(filePath, FileMode.Create,
                                  FileAccess.Write, FileShare.None))
            {
                //read from the input stream in 65000 byte chunks
                const int bufferLen = 65000;
                byte[] buffer = new byte[bufferLen];
                int count = 0;
                while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
                {
                    // save to output stream
                    targetStream.Write(buffer, 0, count);
                }
                targetStream.Close();
                sourceStream.Close();

                request.FileName = filePath;
                DecompressFiles(request);
            }
        }
        catch (Exception ex)
        {
            StreamWriter writer = new StreamWriter(@"C:\upload\temp\message.txt");
            writer.WriteLine(ex);
            writer.WriteLine(File.Exists(@"C:\inetpub\wwwroot\WCFService\Bin\7z.dll"));
            writer.Close();
            File.Delete(request.FileName); //Delete old compressed file
        }
    }

    public void DecompressFiles(RemoteFileInfo fileInfo)
    {
        SevenZipExtractor.SetLibraryPath(@"C:\inetpub\wwwroot\WCFService\Bin\7z64.dll");

        DirectoryInfo diSource = new DirectoryInfo(Path.GetDirectoryName(fileInfo.FileName)); //Get directory info to locate password file
        string tempPath = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileInfo.FileName));
        FileInfo[] fiPass = diSource.GetFiles(tempPath + ".password.7z"); //Locate password file and get information

        if (fiPass.Length == 1) //If it find password file return password
        {
            using (FileStream inStream = File.OpenRead(fiPass[0].FullName)) //Open file to be sent to extractor
            {
                SevenZipExtractor zipExtractor = new SevenZipExtractor(inStream, "shark138513"); //Pass stream and password for extraction
                zipExtractor.ExtractArchive(Path.GetDirectoryName(fileInfo.FileName)); //Extract file to given location
            }
            string encPath = Path.GetDirectoryName(fiPass[0].FullName) + "\\" + Path.GetFileNameWithoutExtension(fiPass[0].FullName);
            StreamReader sr = new StreamReader(encPath); //Create reader to read file
            string password = sr.ReadLine().ToString(); //Pass the password in the file to string to be sent back and used
            sr.Close(); //Close streamreader
            File.Delete(encPath); //Delete decrypted file so password can't be seen
            fileInfo.Password = password;
        }

        if (!fileInfo.FileName.Contains("password")) //Check if password file is missing or corrupt
        {
            using (FileStream inStream = File.OpenRead(fileInfo.FileName)) //Open file to be sent to extractor
            {
                SevenZipExtractor zipExtractor = new SevenZipExtractor(inStream, fileInfo.Password); //Pass stream and password for extraction
                zipExtractor.ExtractArchive(@"C:\upload\" + fileInfo.GroupName + "\\"); //Extract file to given location
            }

            File.Delete(fileInfo.FileName); //Delete old compressed file
        }
    }
}